// var squareRotation = 0.0 // 创建一个变量，用于跟踪正方形的当前旋转

function drawScene(gl, programInfo, buffers, texture, cubeRotation) {
    gl.clearColor(0.0, 0.0, 0.0, 1.0); // Clear to black, fully opaque  清除到黑色，完全不透明
    gl.clearDepth(1.0); // Clear everything 清除所有内容
    gl.enable(gl.DEPTH_TEST); // Enable depth testing
    gl.depthFunc(gl.LEQUAL); // Near things obscure far things  启用深度测试

    // Clear the canvas before we start drawing on it.  在我们开始在画布上绘图之前，需要先清空画布。

    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    // Create a perspective matrix, a special matrix that is
    // used to simulate the distortion of perspective in a camera.
    // Our field of view is 45 degrees, with a width/height
    // ratio that matches the display size of the canvas
    // and we only want to see objects between 0.1 units
    // and 100 units away from the camera.

    /*
    创建一个透视矩阵，这是一种特殊的矩阵，用于模拟相机中的透视失真效果。我们的视场角是45度，宽高比与画布的显示尺寸相匹配，并且我们只想看到距离相机0.1单位到100单位远的对象。
    */

    const fieldOfView = (45 * Math.PI) / 180; // in radians
    const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
    const zNear = 0.1;
    const zFar = 100.0;
    const projectionMatrix = mat4.create();
    // note: glmatrix.js always has the first argument
    // as the destination to receive the result.  注意：在 glMatrix.js 库中，第一个参数总是作为目标接收计算结果。
    mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar);

    // Set the drawing position to the "identity" point, which is
    // the center of the scene.   要将绘制位置设置到场景的“身份”点（通常指的是场景的中心）
    const modelViewMatrix = mat4.create();

    // Now move the drawing position a bit to where we want to
    // start drawing the square.  现在将绘图位置稍微移动到我们想要开始绘制正方形的位置

    mat4.translate(
        modelViewMatrix, // destination matrix  “目标矩阵”或者“目的矩阵”
        modelViewMatrix, // matrix to translate  用于平移的矩阵
        [-0.0, 0.0, -6.0],
    ); // amount to translate 平移量

    // // 2D
    // // 在绘制正方形时将当前旋转应用于正方形。转换为正方形的初始绘图位置后，我们像这样应用旋转
    // mat4.rotate(
    //     modelViewMatrix, // destination matrix
    //     modelViewMatrix, // matrix to rotate
    //     squareRotation, // amount to rotate in radians
    //     [0, 0, 1],
    // ); // axis to rotate around

    // 3D 设置 X Y Z
    mat4.rotate(
        modelViewMatrix, // destination matrix
        modelViewMatrix, // matrix to rotate
        cubeRotation, // amount to rotate in radians
        [0, 0, 1],
    ); // axis to rotate around (Z)
    mat4.rotate(
        modelViewMatrix, // destination matrix
        modelViewMatrix, // matrix to rotate
        cubeRotation * 0.7, // amount to rotate in radians
        [0, 1, 0],
    ); // axis to rotate around (Y)
    mat4.rotate(
        modelViewMatrix, // destination matrix
        modelViewMatrix, // matrix to rotate
        cubeRotation * 0.3, // amount to rotate in radians
        [1, 0, 0],
    ); // axis to rotate around (X)

    // Tell WebGL how to pull out the positions from the position
    // buffer into the vertexPosition attribute.  告诉 WebGL 如何从位置缓冲区中提取位置数据，并将其加载到顶点位置属性中。
    // 模拟灯光
    const normalMatrix = mat4.create();
    mat4.invert(normalMatrix, modelViewMatrix);
    mat4.transpose(normalMatrix, normalMatrix);
    // 创建2D
    setPositionAttribute(gl, buffers, programInfo);
    // 设置着色器
    // setColorAttribute(gl, buffers, programInfo);
    // 设置纹理
    setTextureAttribute(gl, buffers, programInfo);


    // 渲染立方体
    // Tell WebGL which indices to use to index the vertices
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.indices);


    // 设置灯光
    setNormalAttribute(gl, buffers, programInfo);

    // Tell WebGL to use our program when drawing  告诉 WebGL 在绘制时使用我们的程序

    gl.useProgram(programInfo.program);

    // Set the shader uniforms  设置着色器的统一变量。

    gl.uniformMatrix4fv(
        programInfo.uniformLocations.projectionMatrix,
        false,
        projectionMatrix,
    );
    gl.uniformMatrix4fv(
        programInfo.uniformLocations.modelViewMatrix,
        false,
        modelViewMatrix,
    );

    // 模拟灯光
    gl.uniformMatrix4fv(
        programInfo.uniformLocations.normalMatrix,
        false,
        normalMatrix
    );


    // 指定要映射到面的纹理。
    // Tell WebGL we want to affect texture unit 0
    gl.activeTexture(gl.TEXTURE0);

    // Bind the texture to texture unit 0
    gl.bindTexture(gl.TEXTURE_2D, texture);

    // Tell the shader we bound the texture to texture unit 0
    gl.uniform1i(programInfo.uniformLocations.uSampler, 0);

    // // 2D
    // {
    //     const offset = 0;
    //     const vertexCount = 4;
    //     gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount);
    // }

    // 3D
    {
        const vertexCount = 36;
        const type = gl.UNSIGNED_SHORT;
        const offset = 0;
        gl.drawElements(gl.TRIANGLES, vertexCount, type, offset);
    }

}

// Tell WebGL how to pull out the positions from the position
// buffer into the vertexPosition attribute.  告诉 WebGL 如何从位置缓冲区中提取位置数据，并将其加载到顶点位置属性中。
function setColorAttribute(gl, buffers, programInfo) {
    const numComponents = 4; // pull out 4 values per iteration  在每次迭代中提取4个值
    const type = gl.FLOAT; // the data in the buffer is 32bit floats  缓冲区中的数据是32位浮点数。
    const normalize = false; // don't normalize  不要进行归一化。
    const stride = 0; // how many bytes to get from one set of values to the next  从一组值到下一组值需要获取多少字节。
    // 0 = use type and numComponents above  使用上面指定的数据类型和每个顶点的组件数量。
    const offset = 0; // how many bytes inside the buffer to start from  从缓冲区中的多少字节开始。
    gl.bindBuffer(gl.ARRAY_BUFFER, buffers.color);
    gl.vertexAttribPointer(
        programInfo.attribLocations.vertexColor,
        numComponents,
        type,
        normalize,
        stride,
        offset,
    );
    gl.enableVertexAttribArray(programInfo.attribLocations.vertexColor);
}

function setPositionAttribute(gl, buffers, programInfo) {
    {
        // 2D 的变量
        // const numComponents = 2; // pull out 2 values per iteration  在每次迭代中提取两个值
        // 3D 的变量
        const numComponents = 3; // pull out 3 values per iteration  在每次迭代中提取3个值
        const type = gl.FLOAT; // the data in the buffer is 32bit floats  缓冲区中的数据是32位浮点数。
        const normalize = false; // don't normalize  不要进行归一化。
        const stride = 0; // how many bytes to get from one set of values to the next  从一组值到下一组值需要获取多少字节。
        // 0 = use type and numComponents above  使用上面指定的数据类型和每个顶点的组件数量。
        const offset = 0; // how many bytes inside the buffer to start from  从缓冲区中的多少字节开始。
        gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
        gl.vertexAttribPointer(
            programInfo.attribLocations.vertexPosition,
            numComponents,
            type,
            normalize,
            stride,
            offset,
        );
        gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
    }
}


// 告诉 WebGL 如何从缓冲区中提取纹理坐标
function setTextureAttribute(gl, buffers, programInfo) {
    const num = 2; // 每个坐标由 2 个值组成
    const type = gl.FLOAT; // 缓冲区中的数据为 32 位浮点数
    const normalize = false; // 不做标准化处理
    const stride = 0; // 从一个坐标到下一个坐标要获取多少字节
    const offset = 0; // 从缓冲区内的第几个字节开始获取数据
    gl.bindBuffer(gl.ARRAY_BUFFER, buffers.textureCoord);
    gl.vertexAttribPointer(
        programInfo.attribLocations.textureCoord,
        num,
        type,
        normalize,
        stride,
        offset,
    );
    gl.enableVertexAttribArray(programInfo.attribLocations.textureCoord);
}

// 设置模拟灯光
function setNormalAttribute(gl, buffers, programInfo) {
    const numComponents = 3;
    const type = gl.FLOAT;
    const normalize = false;
    const stride = 0;
    const offset = 0;
    gl.bindBuffer(gl.ARRAY_BUFFER, buffers.normal);
    gl.vertexAttribPointer(
        programInfo.attribLocations.vertexNormal,
        numComponents,
        type,
        normalize,
        stride,
        offset);
    gl.enableVertexAttribArray(programInfo.attribLocations.vertexNormal);
}
export { drawScene };